package cn.maihe.elg.operation.utils;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URLEncoder;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.Calendar;
import java.util.Date;
import java.util.Base64;

public class CaTokenUtil {

    /**
     * 默认超时时间5min
     */
    private static int timeOut = 60 * 5;

    /**
     * 创建token
     */
    public static String createToken(String appKey, String appSecret) {
        return createToken(appKey, appSecret, timeOut);
    }

    public static String createToken(String appKey, String appSecret, int TimeOut) {
        if (StringUtil.isBlank(appKey) || StringUtil.isBlank(appSecret)) {
            throw new RuntimeException("appKey|appSecret不能为空");
        }

        if (TimeOut == 0)
            TimeOut = timeOut;

        try {
            Calendar calendar = Calendar.getInstance();
            Date datenow = calendar.getTime();
            Integer num = (int) ((datenow.getTime() / 1000) + TimeOut);
            String P1 = num.toString();
            String str = URLEncoder.encode(P1, String.valueOf(StandardCharsets.UTF_8));
            String P2 = encode(str);
            byte[] b = hmacSha1(P2, appSecret);
            String P4 = encode(b).replace("+", "-").replace("/", "_");
            String result = appKey + "@" + P4 + "@" + P2;
            return result;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 验证token
     */
    public static boolean validateToken(String token, String appKey, String appSecret) {
        if (StringUtil.isBlank(token) || StringUtil.isBlank(appKey) || StringUtil.isBlank(appSecret)) {
            return false;
        }

        if (token.indexOf("@") <= 0) {
            return false;
        }

        String[] p = token.split("@");
        String p1Appkey = p[0];
        String p2 = p[1];
        String p3 = p[2];

        if (!p1Appkey.equals(appKey)) {
            return false;
        }

        byte[] b = hmacSha1(p3, appSecret);
        String p4 = encode(b).replace("+", "-").replace("/", "_");

        if (!p4.equals(p2)) {
            return false;
        }

        Integer time = Integer.parseInt(decode(p3));
        Integer now = (int) (new Date().getTime() / 1000);

        return time >= now;
    }

    private static String encode(byte[] s) {
        if (s == null) return null;
        return Base64.getEncoder().encodeToString(s);
    }

    private static String encode(String s) {
        if (StringUtil.isBlank(s)) return null;
        return encode(s.getBytes(StandardCharsets.UTF_8));
    }

    private static byte[] decodeBuffer(String s) {
        if (StringUtil.isBlank(s)) return null;
        try {
            return Base64.getDecoder().decode(s);
        } catch (Exception e) {
            return null;
        }
    }

    private static String decode(String s) {
        byte[] b = decodeBuffer(s);
        if (b == null) return null;
        return new String(b, StandardCharsets.UTF_8);
    }

    private static byte[] hmacSha1(String data, String key) {
        try {
            SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA1");
            Mac mac = Mac.getInstance("HmacSHA1");
            mac.init(signingKey);
            return mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
        } catch (Exception e) {
            return new byte[0];
        }
    }
}
